package com.sparrow.source.common.utils;

import com.sparrow.source.common.config.MinioConfig;
import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.ObjectWriteResponse;
import io.minio.PutObjectArgs;
import io.minio.SetBucketPolicyArgs;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author bryceyung
 * @since 2021/9/15
 */
@Component
@Slf4j
public class MinioUtils {

    @Autowired
    private MinioClient minioClient;

    @Autowired
    private MinioConfig minioConfig;

    private static final String BUCKET_PARAM = "${bucket}";

    private static final String READ_WRITE =
            "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucket\",\"s3:ListBucketMultipartUploads\"],\"Resource\":[\"arn:aws:s3:::"
                    + BUCKET_PARAM
                    + "\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:DeleteObject\",\"s3:GetObject\",\"s3:ListMultipartUploadParts\",\"s3:PutObject\",\"s3:AbortMultipartUpload\"],\"Resource\":[\"arn:aws:s3:::"
                    + BUCKET_PARAM + "/*\"]}]}";

    public String uploadFileMinio(MultipartFile file, String bucket) {
        try {
            if (isExist(bucket)) {
                log.info("存储桶已经存在！");
            } else {
                //创建存储桶并设置d读写权限
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucket).build());
                minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucket).config(READ_WRITE.replace(BUCKET_PARAM, bucket)).build());
            }
            String filename = file.getOriginalFilename();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
            // 设置存储对象名称
            String objectName = sdf.format(new Date()) + "/" + filename;
            InputStream in = file.getInputStream();
            ObjectWriteResponse response = minioClient.putObject(PutObjectArgs.builder().bucket(bucket).object(objectName).stream(in, in.available(), -1).contentType(file.getContentType()).build());
            String url = String.format("%s/%s/%s", minioConfig.getEndpoint(), bucket, response.object());
            log.info("文件上传成功!");
            return url;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return null;
        }
    }

    /**
     * 流格式存储
     *
     * @param contentType file.getContentType
     * @param fileName file.getOriginalFilename
     * @param in file.getInputStream
     * @param bucket
     * @return
     */
    public String uploadWithStream(String contentType, String fileName, InputStream in, String bucket) {
        try {
            if (isExist(bucket)) {
                log.info("存储桶已经存在！");
            } else {
                //创建存储桶并设置设置d读写读写权限
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucket).build());
                minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucket).config(READ_WRITE.replace(BUCKET_PARAM, bucket)).build());
            }
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            // 设置存储对象名称
            String objectName = sdf.format(new Date()) + "/" + fileName;
            ObjectWriteResponse response = minioClient.putObject(PutObjectArgs.builder().bucket(bucket).object(objectName).stream(in, in.available(), -1).contentType(contentType).build());
            String url = String.format("%s/%s/%s", minioConfig.getEndpoint(), bucket, response.object());
            // 流关闭
            if(in!=null){
                in.close();
            }
            log.info("文件上传成功!");
            return url;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return null;
        }
    }

    /**
     * 判断桶是否存在
     *
     * @param bucket
     * @return
     * @throws Exception
     */
    public boolean isExist(String bucket) throws Exception {
        return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucket).build());
    }
}